//
//  OASectionConfig.m
//  OASDK_Works
//
//  Created by ChenJie on 3/29/20.
//  Copyright © 2020 Mist. All rights reserved.
//

#import "OASectionConfig.h"
#import "OATableConfig.h"
#import "OALog.h"

#define kDefaultSectionTitle @" "
#define kDefaultSectionHeight 0.0000000001

static NSInteger _sectionIdSequence = 0;

@interface OASectionConfig ()

@property (nonatomic, assign, class) NSInteger sectionIdSequence;
@property (nonatomic, copy) NSString *cellType;
@property (nonatomic, strong) NSMutableArray<OACellConfig *> *cells;
@property (nonatomic, strong) NSMutableDictionary<NSString *, OACellConfig *> *cellPool;

@end

@implementation OASectionConfig

#pragma mark - Lifecycle methods

- (instancetype)init {
    self = [super init];
    if (self) {
    }
    return self;
}

- (instancetype)initWithName:(NSString *)name {
    self = [self init];
    if (self) {
        self.name = name;
    }
    return self;
}

+ (instancetype)sectionWithName:(NSString *)name {
    return [[OASectionConfig alloc] initWithName:name];
}

+ (instancetype)section {
    return [[OASectionConfig alloc] init];
}

#pragma mark - Public methods

/* add cell */
- (OACellConfig *)addCell:(OACellConfig *)cell {
    return [self insertCell:cell atIndex:self.cells.count];
}

- (OACellConfig *)addCellWithType:(NSString *)cellType viewModel:(id)viewModel {
    OACellConfig *cellConfig = [OACellConfig cellWithType:cellType viewModel:viewModel];
    return [self addCell:cellConfig];
}

- (OACellConfig *)addCellWithType:(NSString *)cellType staticHeight:(CGFloat)staticHeight viewModel:(id)viewModel {
    OACellConfig *cellConfig = [OACellConfig cellWithType:cellType staticHeight:staticHeight viewModel:viewModel];
    return [self addCell:cellConfig];
}

- (OACellConfig *)addCellWithName:(NSString *)cellName type:(NSString *)cellType viewModel:(id)viewModel {
    OACellConfig *cellConfig = [OACellConfig cellWithName:cellName cellType:cellType viewModel:viewModel];
    return [self addCell:cellConfig];
}

- (OACellConfig *)addCellWithName:(NSString *)cellName
                             type:(NSString *)cellType
                     staticHeight:(CGFloat)staticHeight
                        viewModel:(id)viewModel{
    
    OACellConfig *cellConfig = [OACellConfig cellWithName:cellName
                                                 cellType:cellType
                                             staticHeight:staticHeight
                                                viewModel:viewModel];
    return [self addCell:cellConfig];
}


//
//- (OACellConfig *)addCellWithViewModel:(id<OACellViewModelProtocol>)cellViewModel {
//    OACellConfig *cellConfig = [OACellConfig cellWithCellViewModel:cellViewModel];
//    return [self addCellConfig:cellConfig];
//}

/* insert Cell */
- (OACellConfig *)insertCell:(OACellConfig *)cell atIndex:(NSInteger)cellIndex {
    
    if (!cell) {
        return nil;
    }
    
    if (self.cellPool[cell.name]) {
        return nil;
    }
    
    if (cellIndex > self.cells.count) {
        cellIndex = self.cells.count;
    }
    
    __weak typeof(self) weakSelf = self;
    
    cell.sectionOfCell = ^OASectionConfig *(void) {
        return weakSelf;
    };
    
    cell.indexPathOfCell = ^NSIndexPath *(OACellConfig *cellConfig) {
        NSInteger cellIndex = [weakSelf.cells indexOfObject:cellConfig];
        return [NSIndexPath indexPathForRow:cellIndex inSection:weakSelf.sectionIndex];
    };
    
    [self.cells insertObject:cell atIndex:cellIndex];
    self.cellPool[cell.name] = cell;
    
    return cell;
}

- (OACellConfig *)insertCell:(OACellConfig *)cell beforeCell:(OACellConfig *)referenceCell {
    NSInteger cellIndex = [self.cells indexOfObject:referenceCell];
    return [self insertCell:cell atIndex:cellIndex];
}

- (OACellConfig *)insertCell:(OACellConfig *)cell afterCell:(OACellConfig *)referenceCell {
    NSInteger cellIndex = [self.cells indexOfObject:referenceCell];
    return [self insertCell:cell atIndex:cellIndex + 1];
}

/* delete cell */
- (void)deleteCell:(OACellConfig *)cell {
    if (!cell) {
        return;
    }
    [self.cells removeObject:cell];
    [self.cellPool removeObjectForKey:cell.name];
}

- (void)deleteCellAtIndex:(NSInteger)cellIndex {
    OACellConfig *cellConfig = [self cellConfigAtIndex:cellIndex];
    [self deleteCell:cellConfig];
}

- (void)deleteCellWithName:(NSString *)cellName {
    OACellConfig *cellConfig = [self cellWithName:cellName];
    [self deleteCell:cellConfig];
}

- (void)deleteCellBeforeCell:(OACellConfig *)referenceCell {
    NSInteger cellIndex = [self.cells indexOfObject:referenceCell];
    [self deleteCellAtIndex:cellIndex - 1];
}

- (void)deleteCellAfterCell:(OACellConfig *)referenceCell {
    NSInteger cellIndex = [self.cells indexOfObject:referenceCell];
    [self deleteCellAtIndex:cellIndex + 1];
}

/* get cell */
- (OACellConfig *)cellAtIndex:(NSInteger)cellIndex {
    if (cellIndex >= self.cells.count) {
        return nil;
    }
    return self.cells[cellIndex];
}

- (OACellConfig *)cellWithName:(NSString *)cellName {
    if (!cellName) {
        return nil;
    }
    return self.cellPool[cellName];
}

/* get cellViewModel */
- (id<OACellViewModelProtocol>)viewModelAtIndex:(NSInteger)cellIndex {
    OACellConfig *cellConfig = [self cellAtIndex:cellIndex];
    return cellConfig.cellViewModel;
}

- (id<OACellViewModelProtocol>)viewModelWithName:(NSString *)cellName {
    OACellConfig *cellConfig = [self cellWithName:cellName];
    return cellConfig.cellViewModel;
}

/* update cell */
- (void)updateCell:(OACellConfig *)cell {
    [self updateCell:cell withAnimation:UITableViewRowAnimationNone];
}

- (void)updateCell:(OACellConfig *)cell withAnimation:(UITableViewRowAnimation)animation {
    [self.tableConfig updateCellAtIndexPath:cell.indexPath withAnimation:animation];
}

/* update section */
- (void)updateSection {
    [self updateSectionWithAnimation:UITableViewRowAnimationNone];
}

- (void)updateSectionWithAnimation:(UITableViewRowAnimation)animation {
    [self.tableConfig updateSection:self withAnimation:animation];
}

#pragma mark - Delegate methods

/* UITableViewDataSource */
- (NSInteger)numberOfRowsInSection {
    return self.cells.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndex:(NSInteger)cellIndex {
    OACellConfig *cellConfig = [self cellConfigAtIndex:cellIndex];
    return [cellConfig cellForRowWithTableView:tableView];
}

/* UITableViewDelegate */
- (CGFloat)heightForRowWithCellWidth:(CGFloat)cellWidth cellIndex:(NSInteger)cellIndex {
    OACellConfig *cellConfig = [self cellConfigAtIndex:cellIndex];
    return [cellConfig heightForRowWithCellWidth:cellWidth];
}

- (void)didSelectRowAtIndex:(NSInteger)cellIndex {
    OACellConfig *cellConfig = [self cellConfigAtIndex:cellIndex];
    [cellConfig didSelectRow];
}

#pragma mark - Private methods

- (OACellConfig *)cellConfigAtIndex:(NSInteger)cellIndex {
    if (self.cells.count <= cellIndex) {
        return nil;
    }
    return self.cells[cellIndex];
}

#pragma mark - Delegate methods



#pragma mark - Setter

+ (void)setSectionIdSequence:(NSInteger)sectionIdSequence {
    _sectionIdSequence = sectionIdSequence;
}

#pragma mark - Getter

+ (NSInteger)sectionIdSequence {
    return _sectionIdSequence;
}

- (NSString *)name {
    if (!_name) {
        _name = [NSString stringWithFormat:@"section_%ld", (long)OASectionConfig.sectionIdSequence++];
    }
    return _name;
}

- (NSMutableArray<OACellConfig *> *)cells {
    if (!_cells) {
        _cells = [NSMutableArray array];
    }
    return _cells;
}

- (NSInteger)sectionIndex {
    if (!self.indexOfSection) {
        return 0;
    }
    return self.indexOfSection(self);
}

- (OATableConfig *)tableConfig {
    if (!self.tableOfSection) {
        return nil;
    }
    return self.tableOfSection();
}

- (NSString *)headerTitle {
    if (!_headerTitle || _headerTitle.length == 0) {
        _headerTitle = kDefaultSectionTitle;
    }
    return _headerTitle;
}

- (NSString *)footerTitle {
    if (!_footerTitle || _footerTitle.length == 0) {
        _footerTitle = kDefaultSectionTitle;
    }
    return _footerTitle;
}

- (CGFloat)headerHeight {
    if (!_headerHeight) {
        _headerHeight = kDefaultSectionHeight;
    }
    return _headerHeight;
}

- (CGFloat)footerHeight {
    if (!_footerHeight) {
        _footerHeight = kDefaultSectionHeight;
    }
    return _footerHeight;
}

- (NSMutableDictionary<NSString *,OACellConfig *> *)cellPool {
    if (!_cellPool) {
        _cellPool = [NSMutableDictionary dictionary];
    }
    return _cellPool;
}

#pragma mark - Memory management methods

- (void)dealloc {
    OALogFunction
}

@end
